昨天展示了,如何把 Demo 的實驗給 run 起來,今天來講解實驗流程大概有哪些東西,以及這程式碼做了些什麼事情。主要以註解的方式呈現。
通常一個實驗流程,多少會有以下這些階段
歡迎資訊,會簡單歡迎一下受試者。可能會說一下主試者的背景,以及這個實驗的名稱(也可能不會,怕受試者會有預期效果)
指導語,會說一下這個實驗大概在做什麼主題、想知道什麼事情。受試者需要做哪些事情,以及注意事項。
練習階段,先讓受試者熟悉一下等等要要什麼事情。基本上會跟正式階段要作的事情一樣,只是要做的題數會比較少。通常每一題會被叫做一個嘗試次(trial)。通常一個嘗試次可能會兩個部分組成:凝視的頁面、跟呈現刺激材料的頁面。
凝視的頁面,常常會是一個黑色的小十字。這是為了讓受試者將注意力放在螢幕的中間,減少實驗的變因。等到一段時間後,螢幕畫面會自動變成呈現刺激材料的頁面。受試者看到刺激材料後,就要透過按鍵盡量且快速地做出正確的回答。
正式階段,就是實驗設計者主要收集資訊的階段。實驗設計的獨變項,會在許多嘗試次中用不同的方式呈現出來。
以上是常見的,透過電腦軟體來進行的心理學實驗流程。心理學的實驗設計與流程絕對不只這一種,只是剛好 demo 的程式剛好符合這個流程,所以拿出來當作說明。
接下來透過註解的方式,來說明程式的結構跟心理實驗流程有很多可以對應的地方。
<!DOCTYPE html>
<html>
<head>
<title>My experiment</title>
<!-- 引入運行 jspsych 需要的程式碼套件 -->
<script src="https://unpkg.com/jspsych@7.3.3"></script>
<script src="https://unpkg.com/@jspsych/plugin-html-keyboard-response@1.1.2"></script>
<script src="https://unpkg.com/@jspsych/plugin-image-keyboard-response@1.1.2"></script>
<script src="https://unpkg.com/@jspsych/plugin-preload@1.1.2"></script>
<link href="https://unpkg.com/jspsych@7.3.3/css/jspsych.css" rel="stylesheet" type="text/css" />
</head>
<body></body>
<script>
/**
* initialize jsPsych
*
* 這段主要是在初始化 JsPsych。
* 當實驗結束後,就執行一個函式
* 這個函式會執行 `jsPsych.data.displayData();` 指令
* 在網頁上呈現剛才實驗的數據結果
*/
var jsPsych = initJsPsych({
on_finish: function() {
jsPsych.data.displayData();
}
});
/**
* create timeline
*
* 建立一個空的陣列。等等需要的實驗流程資訊會被放到這裡面
*/
var timeline = [];
/**
* preload images
*
* 先宣告等等在實驗中會用到的實驗素材圖片路徑
* 在實驗開始前,先預下載到網頁上,這樣在正式實驗時就可快速顯時圖片出來
* 最後將這個預下載的實驗流程,放進 timeline 陣列裡面
*
* jsPsychPreload 是 jspsych 提供的功能
* 可以預先載入檔案素材
* https://www.jspsych.org/7.3/plugins/preload/
*/
var preload = {
type: jsPsychPreload,
images: ['img/blue.png', 'img/orange.png']
};
timeline.push(preload);
/**
* define welcome message trial
*
* 歡迎資訊。慣例在實驗開始前,會先跟受試者打聲招呼
* 說謝謝你來當白老鼠(誤)來參與實驗
*
* jsPsychHtmlKeyboardResponse 是 jspsych 提供的功能
* 可以紀錄鍵盤產生的回應
* https://www.jspsych.org/7.3/plugins/html-keyboard-response/
*/
var welcome = {
type: jsPsychHtmlKeyboardResponse,
stimulus: "Welcome to the experiment. Press any key to begin."
};
timeline.push(welcome);
/**
* define instructions trial
*
* 指導語
* 主試者跟受試者說,等等實驗要做什麼事情、以及注意事項
*/
var instructions = {
type: jsPsychHtmlKeyboardResponse,
stimulus: `
<p>In this experiment, a circle will appear in the center
of the screen.</p><p>If the circle is <strong>blue</strong>,
press the letter F on the keyboard as fast as you can.</p>
<p>If the circle is <strong>orange</strong>, press the letter J
as fast as you can.</p>
<div style='width: 700px;'>
<div style='float: left;'><img src='img/blue.png'></img>
<p class='small'><strong>Press the F key</strong></p></div>
<div style='float: right;'><img src='img/orange.png'></img>
<p class='small'><strong>Press the J key</strong></p></div>
</div>
<p>Press any key to begin.</p>
`,
post_trial_gap: 2000
};
timeline.push(instructions);
/**
* define trial stimuli array for timeline variables
*
* 定義等等的刺激材料,對應的正確反應按鍵是什麼
* 藍色的圖片,要按 f 才正確
* 橘色的圖片,要按 j 才正確
*/
var test_stimuli = [
{ stimulus: "img/blue.png", correct_response: 'f'},
{ stimulus: "img/orange.png", correct_response: 'j'}
];
/**
* define fixation and test trials
*
* 設定凝視點,以及嘗試次
*
* 每個嘗試次的凝視階段,會有隨機的呈現時間,從 250ms ~ 2000ms
*
* 嘗試次階段,會把刺激材料呈現出來
* 並且紀錄受試者按的按鈕,並且確認有沒有答對
*
*/
var fixation = {
type: jsPsychHtmlKeyboardResponse,
stimulus: '<div style="font-size:60px;">+</div>',
choices: "NO_KEYS",
trial_duration: function(){
return jsPsych.randomization.sampleWithoutReplacement([250, 500, 750, 1000, 1250, 1500, 1750, 2000], 1)[0];
},
data: {
task: 'fixation'
}
};
var test = {
type: jsPsychImageKeyboardResponse,
stimulus: jsPsych.timelineVariable('stimulus'),
choices: ['f', 'j'],
data: {
task: 'response',
correct_response: jsPsych.timelineVariable('correct_response')
},
on_finish: function(data){
data.correct = jsPsych.pluginAPI.compareKeys(data.response, data.correct_response);
}
};
/**
* define test procedure
*
* 定義在測試階段資料中,想設定的資訊
*
* timeline: 這個階段想要有哪些次要階段
* timeline_variables: 這個階段想引入哪些刺激材料
* repetitions: 想要重複的次數
* randomize_order: 是否要隨機分派呈現順序
*
* 由於這是 demo 實驗,所以沒有正式階段
*/
var test_procedure = {
timeline: [fixation, test],
timeline_variables: test_stimuli,
repetitions: 5,
randomize_order: true
};
timeline.push(test_procedure);
/**
* define debrief
*
* 這段是實驗執行完成後,會先呈現一些簡單的結果數據給受試者看
*
* trials: 把被標記為 response 的 task 資料給撈出來
* correct_trials: 把作答是正確的 trials 資料給撈出來
* accuracy: 計算受試者在實驗中的整體作答平均正確率
* rt: 計算受試者在實驗中的整體作答平均反應時間
*/
var debrief_block = {
type: jsPsychHtmlKeyboardResponse,
stimulus: function() {
var trials = jsPsych.data.get().filter({task: 'response'});
var correct_trials = trials.filter({correct: true});
var accuracy = Math.round(correct_trials.count() / trials.count() * 100);
var rt = Math.round(correct_trials.select('rt').mean());
return `<p>You responded correctly on ${accuracy}% of the trials.</p>
<p>Your average response time was ${rt}ms.</p>
<p>Press any key to complete the experiment. Thank you!</p>`;
}
};
timeline.push(debrief_block);
/**
* 這段是實際執行實驗的程式碼
* 前面的程式碼都只是在設定而已,還沒有正式執行
* 等到這一行時才會開始執行
*/
jsPsych.run(timeline);
</script>
</html>
今天簡單介紹的心理學實驗流程,以及 jspsych demo 的程式註解。明天來談一下怎麼解讀實驗的數據。